﻿using System;
using System.Drawing;
using System.Windows.Forms;
using GraphDrawing2.Canvas;
using GraphDrawing2.Concrete.Model;
using GraphDrawing2.Core;
using Appearance = GraphDrawing2.Core.Appearance;

namespace GraphDrawing2.Concrete.Renderers
{
    public class BackgroundRenderer : IPainter
    {
        readonly ViewPortModel viewPort;
        readonly bool showGrid;
        readonly int gridSize;

        public Appearance Background { get; private set; }
        public LineAppearance Grid { get; private set; }

        BackgroundRenderer(ViewPortModel viewPort, bool showGrid, int gridSize)
        {
            this.viewPort = viewPort;
            Background = new Appearance();
            Grid = new LineAppearance();
            this.showGrid = showGrid;
            this.gridSize = gridSize;
        }

        public BackgroundRenderer(ViewPortModel viewPort, int gridSize) : this(viewPort, true,gridSize)
        {
        }

        public BackgroundRenderer(ViewPortModel viewPort) : this(viewPort, false, 0)
        {
        }

        public void Draw(DrawingContext dc)
        {
            DrawHud(dc.graphics);
        }

        void DrawHud(Graphics g)
        {
            var v = g.Save();
            g.ResetTransform();
            using (var b = Background.CreateBrush())
                g.FillRectangle(b, new Rectangle(new Point(), viewPort.Size));
            g.Restore(v);

            if (showGrid)
                return;
            Func<float, float> Adjust = i => i - i%gridSize;
            var viewTopLeft = viewPort.ToWorld(new PointF(0, 0));
            var leftVertLine = Adjust(viewTopLeft.X);
            var topHorzLine = Adjust(viewTopLeft.Y);

            var viewBottomRight = viewPort.ToWorld(new PointF(viewPort.Size.Width, viewPort.Size.Height));
            var rightVertLine = Adjust(viewBottomRight.X);
            var bottomHorzLine = Adjust(viewBottomRight.Y);
            using (var pen = Grid.CreatePen())
            {
                for (var x = leftVertLine; x <= rightVertLine; x += gridSize)
                    g.DrawLine(pen, x, viewTopLeft.Y, x, viewBottomRight.Y);
                for (var y = topHorzLine; y <= bottomHorzLine; y += gridSize)
                    g.DrawLine(pen, viewTopLeft.X, y, viewBottomRight.X, y);
            }
        }
    }
}